﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Aurora.DataAccess;
using Aurora.Domain;
using Aurora.Infrastructure;
using ComponentFactory.Krypton.Toolkit;

namespace Aurora.Core.ViewForms
{
    public partial class frmVisit : KryptonForm
    {
        private readonly IRepository _repository;
        private readonly long? _id;
        private IList<Service> _services;

        private frmVisit()
        {
        }

        public frmVisit(IRepository repository, long? id)
        {
            _id = id;
            _repository = repository;
            _services = _repository.GetObjects<Service>();
            InitializeComponent();
        }

        /// <summary>
        /// Заполняет список пациентов
        /// </summary>
        /// <param name="filter">критерий фильтрации</param>
        /// <param name="id"></param>
        private void CardsFill(string filter, long? id)
        {
            var cardsDs = id == null
                             ? (from clientCard in _repository.GetObjects<ClientCard>()
                                where clientCard.LastName.Contains(filter)
                                select new { clientCard.Id, Name = clientCard.GetFullName()}).ToList()
                             : (from clientCard in _repository.GetObjects<ClientCard>()
                                where clientCard.Id == id
                                select new { clientCard.Id, Name = clientCard.GetFullName()}).ToList();

            cmbVisitLastName.DataSource = cardsDs;
            cmbVisitLastName.DisplayMember = "Name";
            cmbVisitLastName.ValueMember = "Id";            
        }

        private void DoctorsFill(string filter)
        {
            var doctorsDs = (from doctor in _repository.GetObjects<Doctor>()
                             where doctor.Name.Contains(filter)
                             select new { doctor.Id, doctor.Name }).ToList();

            cmbVisitDoctor.DataSource = doctorsDs;
            cmbVisitDoctor.DisplayMember = "Name";
            cmbVisitDoctor.ValueMember = "Id";    
        }

        private void DiseasesFill(string filter)
        {
            var diseaseDs = (from disease in _repository.GetObjects<Disease>()
                             where disease.Name.Contains(filter)
                             select new { disease.Id, disease.Name }).ToList();

            cmbVisitDisease.DataSource = diseaseDs;
            cmbVisitDisease.DisplayMember = "Name";
            cmbVisitDisease.ValueMember = "Id";  
        }

        private void ServicesFill()
        {
            lbxServices.DataSource = _services;
            lbxServices.DisplayMember = "Name";
            lbxServices.ValueMember = "Id";
        }

        private void AddDiagnosis()
        {
            try
            {
                if (tbDiagnosisInfo.Text.Length <= 10)
                    Messenger.ShowErrorMessage("Ошибка валидации", "Пожалуйста, введите корректный анамнез!");
                else
                {
                    foreach (var id in from DataGridViewRow row in dgDiagnosis.Rows select (Int64) row.Cells["Id"].Value)
                    {
                        if (id == (Int64)cmbVisitDisease.SelectedValue)
                        {
                            Messenger.ShowExclamation("Этот диагноз уже добавлен.");
                            return;
                        }
                    }

                    dgDiagnosis.Rows.Add((Int64) cmbVisitDisease.SelectedValue, 
                                         cmbVisitDisease.Text,
                                         tbDiagnosisInfo.Text);
                }
            }
            catch (Exception exception)
            {
                Messenger.ShowErrorMessage("Непредвиденное исключение", exception.Message);
            }
        }

        private void ShowAddForm()
        {
            var frmAddEdit = new frmAddEdit(_repository);
            Enabled = false;
            frmAddEdit.ShowDialog(this);
            Enabled = true;
        }

        private ICollection<Diagnosis> GetDiagnosesList()
        {
            return (from DataGridViewRow row in dgDiagnosis.Rows
                    select Diagnosis.Create(
                                            _repository.GetObject<Disease>(
                                                Int64.Parse(row.Cells["Id"].Value.ToString())), 
                                                row.Cells["Info"].Value.ToString())
                                            ).ToList();
        }

        private void RemoveDiagnosis()
        {
            if (dgDiagnosis.SelectedRows.Count != 1)
            {
                return;
            }

            if(Messenger.ShowYesNoQuestion("Вы действительно желаете удалить выбранный диагноз?") == DialogResult.Yes)
                dgDiagnosis.Rows.Remove(dgDiagnosis.SelectedRows[0]);
            else 
                return;
        }

        private void ServicesProvided()
        {
            var servPrices = from Service service in lbxServices.SelectedItems select service.Price;

            lblNumServices.Text = lbxServices.SelectedItems.Count.ToString();
            lblPriceSum.Text = servPrices.Sum(t => t).ToString();
        }

        private void AddVisit()
        {
            var diagnosis = GetDiagnosesList();
            var visit = Visit.Create(diagnosis, 
                                     _repository.GetObject<Doctor>((Int64)cmbVisitDoctor.SelectedValue), 
                                     dtVisitDate.Value,
                                     _repository.GetObject<ClientCard>((Int64)cmbVisitLastName.SelectedValue));
            
            foreach (Service service in lbxServices.SelectedItems)
            {
                visit.Services.Add(service);
            }

            _repository.Insert(visit);

            if (!_repository.SubmitChanges())
            {
                while(Messenger.ShowYesNoQuestion("При добавлении записи в БД произошла ошибка. Повторить?") != DialogResult.No)
                {
                    if (_repository.SubmitChanges()) break;
                }

                _repository.RejectChanges();
            }
        }

        public void ShowForView(long id)
        {
            if(id < 0) return;
            var visit =
                ((AuroraEntities) _repository.GetContext()).Visits.
                                    Include("VisitDoctor").
                                    Include("RelatedCard").
                                    Include("Services").
                                    Include("VisitDiagnosis.DiagnosisDisease").
                                    Where(t => t.Id == id).
                                    FirstOrDefault();

            btnDone.Enabled = false;

            cmbVisitLastName.SelectedValue = id;
            cmbVisitDoctor.SelectedValue = visit.VisitDoctor.Id;
            cmbVisitLastName.SelectedValue = visit.RelatedCard.Id;

            foreach (var diagnosis in visit.VisitDiagnosis)
            {
                dgDiagnosis.Rows.Add(diagnosis.Id, diagnosis.DiagnosisDisease.Name, diagnosis.DiagnosisInfo);
            }

            _services = visit.Services.ToList();

            frmVisit_Load(this, null);

            for (var i = 0; i < lbxServices.Items.Count; i++ )
            {
                lbxServices.SetSelected(i, true);
            }

            Show();
        }
        
        private void frmVisit_Load(object sender, System.EventArgs e)
        {
            CardsFill(String.Empty, _id);
            DoctorsFill(String.Empty);
            DiseasesFill(String.Empty);
            ServicesFill();
        }

        private void btnMoreAdd_Click(object sender, EventArgs e)
        {
            ShowAddForm();
        }

        private void btnDiagnosisAdd_Click(object sender, EventArgs e)
        {
            AddDiagnosis();
        }

        private void btnRemoveDiagnosis_Click(object sender, EventArgs e)
        {
            RemoveDiagnosis();
        }

        private void lbxServices_SelectedValueChanged(object sender, EventArgs e)
        {
            ServicesProvided();
        }

        private void cmbVisitDisease_KeyUp(object sender, KeyEventArgs e)
        {
            DiseasesFill(cmbVisitDisease.Text);
        }

        private void cmbVisitLastName_KeyUp(object sender, KeyEventArgs e)
        {
            CardsFill(cmbVisitLastName.Text, null);
        }

        private void cmbVisitDoctor_KeyUp(object sender, KeyEventArgs e)
        {
            DiseasesFill(cmbVisitDisease.Text);
        }

        private void btnDone_Click(object sender, EventArgs e)
        {
            if (lbxServices.SelectedItems.Count == 0)
            {
                Messenger.ShowErrorMessage("Ошибка ввода", "Не выбрно ни одной услуги");
                return;
            }

            var result = Messenger.ShowAcceptDeclineChangesQuestion();

            if (result == DialogResult.Cancel) return;

            if (result == DialogResult.Yes) AddVisit();

            Close();
        }
        
        private void btnCancel_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}
